package demoMod.anm2editor.ui;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Interpolation;
import com.google.gson.reflect.TypeToken;
import demoMod.anm2editor.enums.CustomCurveType;
import demoMod.anm2editor.fonts.FontKeys;
import demoMod.anm2editor.localization.LocalizedStrings;
import demoMod.anm2editor.model.Anchor;
import demoMod.anm2editor.model.CustomInterpolation;
import demoMod.anm2editor.model.CustomInterpolationSave;
import demoMod.anm2editor.model.KeyFrame;
import demoMod.anm2editor.utils.Preferences;
import demoMod.gdxform.core.FormManager;
import demoMod.gdxform.enums.GFrameWindowMode;
import demoMod.gdxform.enums.GFrameWindowStyle;
import demoMod.gdxform.helpers.FontHelper;
import demoMod.gdxform.ui.GButton;
import demoMod.gdxform.ui.GFrame;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

/**
 * 曲线数据编辑窗体
 */
public class CurveEditWindow extends GFrame {
    private static final Logger log = LogManager.getLogger(CurveEditWindow.class);

    private final Consumer<Interpolation> callback;

    private final Interpolation currentCurve;

    private final CurveGraph graph;

    /**
     * 是否为自定义曲线，如果为否，用户将不能编辑曲线
     */
    private boolean isCustom;

    /**
     * 选择曲线类型 系统预设/自定义
     */
    private final GButton selectCurveTypeButton;

    /**
     * 选择默认曲线模板 线性/指数/淡入/淡出 等
     */
    private final GButton selectDefaultTemplateButton;

    /**
     * 选择自定义曲线类型 折线/贝塞尔曲线
     */
    private final GButton selectCustomCurveTypeButton;

    private final GButton addAnchorButton;
    private final GButton editAnchorButton;
    private final GButton deleteAnchorButton;

    private final GButton loadPresetButton;
    private final GButton savePresetButton;
    private final GButton deletePresetButton;

    private boolean confirmed = false;

    public CurveEditWindow(KeyFrame frameToBake, List<KeyFrame> bakedFrames, List<KeyFrame> keyFrames, Interpolation currentCurve, Consumer<Interpolation> callback) {
        super(Gdx.graphics.getWidth() / 2.0F - Gdx.graphics.getWidth() * 0.1F, Gdx.graphics.getHeight() / 2.0F - Gdx.graphics.getHeight() * 0.45F, Gdx.graphics.getWidth() * 0.2F, Gdx.graphics.getWidth() * 0.2F + Gdx.graphics.getHeight() * 0.4F, FontHelper.getFont(FontKeys.SIM_HEI_14), GFrameWindowStyle.CLOSE_BUTTON_ONLY, false);
        setWindowMode(GFrameWindowMode.MODAL);
        this.currentCurve = currentCurve;
        List<String> strings = LocalizedStrings.getStrings("CurveEditWindow");
        setTitle(strings.get(0));

        this.graph = new CurveGraph();
        this.graph.setWidth(getWidth() - 6);
        this.graph.setHeight(getWidth() - 6);

        addElement(this.graph);

        isCustom = currentCurve instanceof CustomInterpolation;
        if (isCustom) {
            graph.setCustomCurve((CustomInterpolation) currentCurve);
        } else {
            graph.setDefaultCurve(currentCurve);
        }

        selectCurveTypeButton = new GButton(3, getHeight() * 0.9F, getWidth() * 0.5F, getHeight() * 0.05F, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public void onClick() {
                OptionWindow optionWindow = new OptionWindow(strings.get(11), Arrays.asList(strings.get(1), strings.get(2)), FontHelper.getFont(FontKeys.SIM_HEI_14), isCustom ? 1 : 0);
                optionWindow.setConfirmCallback(index -> {
                    boolean result = index == 1;
                    if (result != isCustom) {
                        selectDefaultTemplateButton.setVisible(!selectDefaultTemplateButton.visible());
                        selectCustomCurveTypeButton.setVisible(!selectCustomCurveTypeButton.visible());
                        addAnchorButton.setVisible(!addAnchorButton.visible());
                        editAnchorButton.setVisible(!editAnchorButton.visible());
                        deleteAnchorButton.setVisible(!deleteAnchorButton.visible());
                        loadPresetButton.setVisible(!loadPresetButton.visible());
                        savePresetButton.setVisible(!savePresetButton.visible());
                        deletePresetButton.setVisible(!deletePresetButton.visible());
                        isCustom = !isCustom;
                        graph.setCustom(isCustom);
                        graph.setCanEditAnchors(isCustom);
                        selectCurveTypeButton.setText(isCustom ? strings.get(2) : strings.get(1));

                        if (isCustom && graph.getCustomCurve() == null) {
                            CustomInterpolation customInterpolation = new CustomInterpolation();
                            customInterpolation.setCurveType(CustomCurveType.BROKEN_LINE);
                            Anchor startingAnchor = new Anchor();
                            startingAnchor.setX(0.0F);
                            startingAnchor.setY(0.0F);
                            startingAnchor.setBezierPoints(new ArrayList<>());

                            Anchor startingBezierPoint = new Anchor();
                            startingBezierPoint.setX(0.1F);
                            startingBezierPoint.setY(0.1F);

                            startingAnchor.getBezierPoints().add(startingBezierPoint);
                            customInterpolation.setStartingAnchor(startingAnchor);
                            Anchor endingAnchor = new Anchor();
                            endingAnchor.setX(1.0F);
                            endingAnchor.setY(1.0F);
                            endingAnchor.setBezierPoints(new ArrayList<>());

                            Anchor endingBezierPoint = new Anchor();
                            endingBezierPoint.setX(0.9F);
                            endingBezierPoint.setY(0.9F);

                            endingAnchor.getBezierPoints().add(endingBezierPoint);
                            customInterpolation.setEndingAnchor(endingAnchor);
                            graph.setCustomCurve(customInterpolation);
                        } else if (!isCustom && graph.getDefaultCurve() == null) { //This shouldn't happen
                            graph.setDefaultCurve(new Interpolation() {
                                @Override
                                public float apply(float a) {
                                    return 0;
                                }
                            });
                        }

                        if (isCustom) {
                            callback.accept(graph.getCustomCurve());
                        } else {
                            callback.accept(graph.getDefaultCurve());
                        }
                    }
                });
            }
        };
        selectCurveTypeButton.setText(isCustom ? strings.get(2) : strings.get(1));
        selectCurveTypeButton.setBackground(Color.ROYAL.cpy());
        addElement(selectCurveTypeButton);

        selectDefaultTemplateButton = new GButton(3, getHeight() * 0.82F, getWidth() * 0.5F, getHeight() * 0.05F, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public void onClick() {
                List<String> options = new ArrayList<>();
                options.add("linear");
                options.add("smooth");
                options.add("smooth2");
                options.add("smoother");
                options.add("pow2");
                options.add("pow2In");
                options.add("pow2Out");
                options.add("pow2InInverse");
                options.add("pow2OutInverse");
                options.add("pow3");
                options.add("pow3In");
                options.add("pow3Out");
                options.add("pow3InInverse");
                options.add("pow3OutInverse");
                options.add("pow4");
                options.add("pow4In");
                options.add("pow4Out");
                options.add("pow5");
                options.add("pow5In");
                options.add("pow5Out");
                options.add("sine");
                options.add("sineIn");
                options.add("sineOut");
                options.add("exp10");
                options.add("exp10In");
                options.add("exp10Out");
                options.add("exp5");
                options.add("exp5In");
                options.add("exp5Out");
                options.add("circle");
                options.add("circleIn");
                options.add("circleOut");
                options.add("elastic");
                options.add("elasticIn");
                options.add("elasticOut");
                options.add("swing");
                options.add("swingIn");
                options.add("swingOut");
                options.add("bounce");
                options.add("bounceIn");
                options.add("bounceOut");
                options.add("static");
                OptionWindow optionWindow = new OptionWindow(strings.get(13), options, FontHelper.getFont(FontKeys.SIM_HEI_14));
                optionWindow.setConfirmCallback(index -> {
                    selectDefaultTemplateButton.setText(options.get(index));
                    if (index < options.size() - 1) {
                        try {
                            Interpolation interpolation = (Interpolation) Interpolation.class.getDeclaredField(options.get(index)).get(null);
                            graph.setDefaultCurve(interpolation);
                        } catch (NoSuchFieldException | IllegalAccessException e) {
                            log.error("", e);
                            return;
                        }
                    } else {
                        graph.setDefaultCurve(new Interpolation() {
                            @Override
                            public float apply(float a) {
                                return 0;
                            }
                        });
                    }
                    callback.accept(graph.getDefaultCurve());
                });
            }
        };
        selectDefaultTemplateButton.setText(strings.get(12));
        selectDefaultTemplateButton.setBackground(Color.ROYAL.cpy());
        addElement(selectDefaultTemplateButton);

        selectCustomCurveTypeButton = new GButton(3, getHeight() * 0.75F, getWidth() * 0.5F, getHeight() * 0.05F, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public void onClick() {
                OptionWindow optionWindow = new OptionWindow(strings.get(14), Arrays.asList(strings.get(3), strings.get(4), strings.get(31)), FontHelper.getFont(FontKeys.SIM_HEI_14), isCustom ? graph.getCustomCurve().getCurveType().ordinal() : 0);
                optionWindow.setConfirmCallback(index -> {
                    switch (index) {
                        case 0: //折线
                            graph.setCustomCurveType(CustomCurveType.BROKEN_LINE);
                            break;
                        case 1: //贝塞尔曲线
                            graph.setCustomCurveType(CustomCurveType.BEZIER_CURVE);
                            break;
                        case 2: //钢笔
                            graph.setCustomCurveType(CustomCurveType.PEN);
                            break;
                    }
                    selectCustomCurveTypeButton.setText(strings.get(getCurveTypeStringIndex()));
                    callback.accept(graph.getCustomCurve());
                });
            }
        };
        selectCustomCurveTypeButton.setText(strings.get(getCurveTypeStringIndex()));
        selectCustomCurveTypeButton.setBackground(Color.ROYAL.cpy());
        addElement(selectCustomCurveTypeButton);

        loadPresetButton = new GButton(3, getHeight() * 0.65F, getWidth() * 0.3F, getHeight() * 0.05F, FontHelper.getFont(FontKeys.SIM_HEI_12)) {
            private int lastSelectedIndex = 0;

            @Override
            public void onClick() {
                File presetDir = new File("curvePresets");
                if (!presetDir.exists()) {
                    presetDir.mkdir();
                }
                File[] presets = presetDir.listFiles((dir, name) -> name.endsWith(".json"));
                if (presets == null) {
                    presets = new File[0];
                }
                List<String> presetList = new ArrayList<>();
                for (File preset : presets) {
                    presetList.add(preset.getName().substring(0, preset.getName().length() - 5));
                }
                OptionWindow optionWindow = new OptionWindow(strings.get(18), presetList, FontHelper.getFont(FontKeys.SIM_HEI_14), Math.min(presetList.size() - 1, lastSelectedIndex));
                File[] finalPresets = presets;
                optionWindow.setConfirmCallback(index -> {
                    try {
                        lastSelectedIndex = index;
                        CustomInterpolationSave interpolationSave = Preferences.getGson().fromJson(Gdx.files.absolute(finalPresets[index].getAbsolutePath()).readString("UTF-8"), new TypeToken<CustomInterpolationSave>() {
                        }.getType());
                        CustomInterpolation customInterpolation = new CustomInterpolation();
                        customInterpolation.setCurveType(interpolationSave.getCurveType());
                        customInterpolation.setStartingAnchor(interpolationSave.getStartingAnchor());
                        customInterpolation.setEndingAnchor(interpolationSave.getEndingAnchor());
                        for (Anchor anchor : interpolationSave.getAnchors()) {
                            customInterpolation.addAnchor(anchor);
                        }
                        graph.setCustomCurve(customInterpolation);

                        selectCustomCurveTypeButton.setText(strings.get(getCurveTypeStringIndex()));
                        callback.accept(customInterpolation);
                    } catch (Throwable e) {
                        log.error("", e);
                        new MessageBox(strings.get(26), strings.get(25), FontHelper.getFont(FontKeys.SIM_HEI_14));
                    }
                });
            }
        };
        loadPresetButton.setText(strings.get(8));
        loadPresetButton.setBackground(Color.ROYAL.cpy());
        addElement(loadPresetButton);

        savePresetButton = new GButton(3 + getWidth() * 0.33F, getHeight() * 0.65F, getWidth() * 0.3F, getHeight() * 0.05F, FontHelper.getFont(FontKeys.SIM_HEI_12)) {
            @Override
            public void onClick() {
                File presetDir = new File("curvePresets");
                if (!presetDir.exists()) {
                    presetDir.mkdir();
                }
                TextInputWindow textInputWindow = new TextInputWindow(strings.get(19), "", FontHelper.getFont(FontKeys.SIM_HEI_14));
                textInputWindow.setCharFilter("[a-zA-Z0-9,.;'\\[\\]{}\\s`~\\-=!@#$%^&()_+]");
                textInputWindow.setConfirmCallback(presetName -> {
                    File presetFile = new File("curvePresets/" + presetName + ".json");
                    if (!presetFile.exists()) {
                        try {
                            presetFile.createNewFile();
                        } catch (IOException e) {
                            new MessageBox(strings.get(26), strings.get(24), FontHelper.getFont(FontKeys.SIM_HEI_14));
                            log.error("", e);
                            return;
                        }
                        savePreset(presetFile);
                    } else {
                        QuestionBox questionBox = new QuestionBox(strings.get(27), strings.get(22), FontHelper.getFont(FontKeys.SIM_HEI_14));
                        questionBox.setConfirmCallback(() -> savePreset(presetFile));
                    }
                });
            }

            private void savePreset(File presetFile) {
                try {
                    OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(presetFile), StandardCharsets.UTF_8);
                    CustomInterpolationSave interpolationSave = new CustomInterpolationSave();
                    CustomInterpolation customInterpolation = graph.getCustomCurve();
                    interpolationSave.setCurveType(customInterpolation.getCurveType());
                    List<Anchor> anchors = customInterpolation.getAnchors();
                    interpolationSave.setStartingAnchor(anchors.get(0));
                    interpolationSave.setEndingAnchor(anchors.get(anchors.size() - 1));
                    List<Anchor> savedAnchors = new ArrayList<>();
                    for (int i=1;i<anchors.size() - 1;i++) {
                        savedAnchors.add(anchors.get(i));
                    }
                    interpolationSave.setAnchors(savedAnchors);
                    writer.write(Preferences.getGson().toJson(interpolationSave));
                    writer.flush();
                    writer.close();
                    log.info("Successfully saved preset.");
                    new MessageBox(strings.get(28), strings.get(29), FontHelper.getFont(FontKeys.SIM_HEI_14));
                } catch (IOException e) {
                    log.error("Exception occurred while saving preset!", e);
                    new MessageBox(strings.get(26), strings.get(24), FontHelper.getFont(FontKeys.SIM_HEI_14));
                }
            }
        };
        savePresetButton.setText(strings.get(9));
        savePresetButton.setBackground(Color.ROYAL.cpy());
        addElement(savePresetButton);

        deletePresetButton = new GButton(3 + getWidth() * 0.66F, getHeight() * 0.65F, getWidth() * 0.3F, getHeight() * 0.05F, FontHelper.getFont(FontKeys.SIM_HEI_12)) {
            private int lastSelectedIndex = 0;

            @Override
            public void onClick() {
                File presetDir = new File("curvePresets");
                if (!presetDir.exists()) {
                    presetDir.mkdir();
                }
                File[] presets = presetDir.listFiles((dir, name) -> name.endsWith(".json"));
                if (presets == null) {
                    presets = new File[0];
                }
                List<String> presetList = new ArrayList<>();
                for (File preset : presets) {
                    presetList.add(preset.getName().substring(0, preset.getName().length() - 5));
                }
                File[] finalPresets = presets;
                OptionWindow optionWindow = new OptionWindow(strings.get(20), presetList, FontHelper.getFont(FontKeys.SIM_HEI_14), Math.min(presetList.size() - 1, lastSelectedIndex));
                optionWindow.setConfirmCallback(index -> {
                    lastSelectedIndex = index;
                    QuestionBox questionBox = new QuestionBox(strings.get(27), strings.get(23), FontHelper.getFont(FontKeys.SIM_HEI_14));
                    questionBox.setConfirmCallback(() -> {
                        if (!finalPresets[index].delete()) {
                            new MessageBox(strings.get(26), strings.get(30), FontHelper.getFont(FontKeys.SIM_HEI_14));
                        }
                    });
                });
            }
        };
        deletePresetButton.setText(strings.get(10));
        deletePresetButton.setBackground(Color.ROYAL.cpy());
        addElement(deletePresetButton);

        addAnchorButton = new GButton(getWidth() * 0.38F, getWidth() + 0.03F * getHeight(), getWidth() * 0.2F, getHeight() * 0.05F, FontHelper.getFont(FontKeys.SIM_HEI_12)) {
            @Override
            public void onClick() {
                List<Anchor> anchors = graph.getCustomCurve().getAnchors();
                Anchor anchor = new Anchor();
                anchor.setX((anchors.get(anchors.size() - 2).getX() + anchors.get(anchors.size() - 1).getX()) / 2.0F);
                anchor.setY((anchors.get(anchors.size() - 2).getY() + anchors.get(anchors.size() - 1).getY()) / 2.0F);
                anchor.setBezierPoints(new ArrayList<>());

                Anchor guideAnchor1 = new Anchor();
                guideAnchor1.setX(anchor.getX() - 0.05F);
                guideAnchor1.setY(anchor.getY());

                Anchor guideAnchor2 = new Anchor();
                guideAnchor2.setX(anchor.getX() + 0.05F);
                guideAnchor2.setY(anchor.getY());

                anchor.getBezierPoints().add(guideAnchor1);
                anchor.getBezierPoints().add(guideAnchor2);
                graph.addAnchor(anchor);
                graph.setCurrentSelectedAnchor(anchor);
                callback.accept(graph.getCustomCurve());
            }
        };
        addAnchorButton.setText(strings.get(5));
        addAnchorButton.setBackground(Color.ROYAL.cpy());
        addElement(addAnchorButton);

        editAnchorButton = new GButton(getWidth() * 0.59F, getWidth() + 0.03F * getHeight(), getWidth() * 0.2F, getHeight() * 0.05F, FontHelper.getFont(FontKeys.SIM_HEI_12)) {
            @Override
            public void onClick() {
                Anchor anchor = graph.getCurrentSelectedAnchor();
                if (anchor != null) {
                    TextInputWindow textInputWindow = new TextInputWindow(strings.get(6), String.format("%.2f,%.2f", anchor.getX(), anchor.getY()), FontHelper.getFont(FontKeys.SIM_HEI_14));
                    textInputWindow.setCharFilter("[0-9.,]");
                    textInputWindow.setConfirmCallback(str -> {
                        str = str.replace(" ", "");
                        String[] tokens = str.split(",");
                        float deltaX = Float.parseFloat(tokens[0]) - anchor.getX();
                        float deltaY = Float.parseFloat(tokens[1]) - anchor.getY();
                        anchor.setX(Float.parseFloat(tokens[0]));
                        anchor.setY(Float.parseFloat(tokens[1]));

                        if (anchor == graph.getCustomCurve().getAnchors().get(0)) {
                            anchor.setX(0.0F);
                            deltaX = 0.0F;
                        }

                        if (anchor == graph.getCustomCurve().getAnchors().get(graph.getCustomCurve().getAnchors().size() - 1)) {
                            anchor.setX(1.0F);
                            deltaX = 0.0F;
                        }

                        for (Anchor guideAnchor : anchor.getBezierPoints()) {
                            guideAnchor.setX(guideAnchor.getX() + deltaX);
                            guideAnchor.setY(guideAnchor.getY() + deltaY);
                        }

                        graph.refreshPoint(anchor);
                        callback.accept(graph.getCustomCurve());
                    });
                }
            }
        };
        editAnchorButton.setText(strings.get(6));
        editAnchorButton.setBackground(Color.ROYAL.cpy());
        addElement(editAnchorButton);

        deleteAnchorButton = new GButton(getWidth() * 0.8F, getWidth() + 0.03F * getHeight(), getWidth() * 0.2F, getHeight() * 0.05F, FontHelper.getFont(FontKeys.SIM_HEI_12)) {
            @Override
            public void onClick() {
                graph.deleteAnchor();
                callback.accept(graph.getCustomCurve());
            }
        };
        deleteAnchorButton.setText(strings.get(7));
        deleteAnchorButton.setBackground(Color.ROYAL.cpy());
        addElement(deleteAnchorButton);

        if (isCustom) {
            this.graph.setCustom(true);
            this.graph.setCanEditAnchors(true);
            selectDefaultTemplateButton.setVisible(false);
        } else {
            selectCustomCurveTypeButton.setVisible(false);
            addAnchorButton.setVisible(false);
            editAnchorButton.setVisible(false);
            deleteAnchorButton.setVisible(false);
            loadPresetButton.setVisible(false);
            savePresetButton.setVisible(false);
            deletePresetButton.setVisible(false);
        }

        this.callback = callback;

        Timeline timeline = ((Timeline)FormManager.getInstance().getContainerById(Timeline.ID));
        GButton confirm = new GButton(3, getWidth() + 0.03F * getHeight(), getWidth() * 0.15F, 20, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public void onClick() {
                confirmed = true;
                FormManager.getInstance().removeContainer(CurveEditWindow.this);
            }
        };
        confirm.setText(strings.get(15));
        confirm.setBackground(new Color(0, 47.0F / 255.0F, 147.0F / 255.0F, 1.0F));
        confirm.setBorderWidth(2);
        confirm.setBorder(Color.LIGHT_GRAY.cpy());
        GButton cancel = new GButton(3 + getWidth() * 0.2F, getWidth() + 0.03F * getHeight(), getWidth() * 0.15F, 20, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public void onClick() {
                FormManager.getInstance().removeContainer(CurveEditWindow.this);
            }
        };
        cancel.setText(strings.get(16));
        cancel.setBackground(Color.LIGHT_GRAY.cpy());
        cancel.setBorderWidth(2);
        cancel.setBorder(Color.LIGHT_GRAY.cpy());

        addElement(confirm);
        addElement(cancel);

        int totalDelay = 0;
        int index = keyFrames.indexOf(frameToBake);
        for (int i=0;i<index;i++) {
            totalDelay += keyFrames.get(i).delay;
        }
        final int startFrameIndex = totalDelay;
        final int endFrameIndex = startFrameIndex + bakedFrames.size();

        GButton preview = new GButton(3, getWidth() + 0.03F * getHeight() + 35, getWidth() * 0.15F, 20, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public void onClick() {
                if (timeline.isPlaying()) {
                    timeline.pause();
                    timeline.setPointerIndex(startFrameIndex);
                } else {
                    timeline.play();
                }
            }

            @Override
            public void update() {
                super.update();
                if (timeline.getPointerIndex() > endFrameIndex || timeline.getPointerIndex() < startFrameIndex) {
                    timeline.setPointerIndex(startFrameIndex);
                }
            }
        };
        preview.setText(strings.get(17));
        preview.setBackground(new Color(0, 47.0F / 255.0F, 147.0F / 255.0F, 1.0F));
        preview.setBorderWidth(2);
        preview.setBorder(Color.LIGHT_GRAY.cpy());

        addElement(preview);
    }

    private int getCurveTypeStringIndex() {
        int customCurveTypeNameIndex = 3;
        if (isCustom) {
            switch (graph.getCustomCurve().getCurveType()) {
                case BROKEN_LINE:
                    break;
                case BEZIER_CURVE:
                    customCurveTypeNameIndex = 4;
                    break;
                case PEN:
                    customCurveTypeNameIndex = 31;
            }
            return customCurveTypeNameIndex;
        }
        return 0;
    }

    @Override
    public void dispose() {
        super.dispose();
        if (confirmed) {
            if (isCustom) {
                this.callback.accept(graph.getCustomCurve());
            } else {
                this.callback.accept(graph.getDefaultCurve());
            }
        } else {
            this.callback.accept(this.currentCurve);
        }
    }

    @Override
    public boolean mouseDragged(int screenX, int screenY) {
        if (isCustom) {
            callback.accept(graph.getCustomCurve());
        }
        return super.mouseDragged(screenX, screenY);
    }
}
